#ifndef K3_WINDOW_H
#define K3_WINDOW_H
#include <vector>
#include <string>
#include <memory>
#include <functional>
#include "Event.h"
struct GLFWmonitor;
struct GLFWvidmode;
struct GLFWwindow;
namespace kptv3
{
    struct WindowConfig
    {
        int     width;
        int     height;
        bool    full_screen;
        bool    v_sync;
        std::string title;
        WindowConfig(
            const std::string &title,
            int w,
            int h,
            bool fs,
            bool vs
        )
        : width(w), height(h), full_screen(fs), v_sync(vs), title(title) {}
    };
    
    class Window
    {
    public:
        Window(WindowConfig w_config);
        ~Window();

        void Display();

        void AddKeyEvent();
        void AddWinCloseEvent();
        void AddWinResizeEvent();
        void AddWinFocusEvent();

    private:
        static unsigned int m_GLFWWindowCount;

        std::shared_ptr<WindowConfig> m_winConf;

        GLFWmonitor* m_CurMonitor;
        GLFWvidmode* m_pVideoMode;
        std::vector<GLFWmonitor*> m_Monitors;


        GLFWwindow* m_Window;


        using WinSizeFunc       = std::function < void ( int , int ) >;
        using WinCloseFunc      = std::function < void ( ) >;
        using WinFocusFunc      = std::function < void ( bool ) >;

        using KeyPressdFunc     = std::function < void ( KeyCode ) >;
        using KeyRepeatedFunc   = KeyPressdFunc;
        using KeyReleasedFunc   = KeyPressdFunc;
        using CharFunc          = KeyPressdFunc;

        using MousePressedFunc  = std::function < void ( MouseCode ) >;
        using MouseReleasedFunc = MousePressedFunc;
        using ScrollFunc        = std::function < void ( float , float ) >;
        using CursorPosFunc     = ScrollFunc;

        struct WindowData
        {
            WindowData() {}
            std::vector<WinSizeFunc> m_winSizeFuncs;
            std::vector<WinCloseFunc> m_winCloseFuncs;
            std::vector<WinFocusFunc> m_winFocusFuncs;
            
            std::vector<KeyPressdFunc> m_keyPressedFuncs;
            std::vector<KeyRepeatedFunc> m_keyRepeatedFuncs;
            std::vector<KeyReleasedFunc> m_keyReleasedFuncs;
            std::vector<CharFunc> m_charFuncs;

            std::vector<MousePressedFunc> m_mousePressedFuncs;
            std::vector<MouseReleasedFunc> m_mouseReleasedFuncs;
            std::vector<ScrollFunc> m_scrollFuncs;
            std::vector<CursorPosFunc> m_cursorPosFuncs;
        };

        std::shared_ptr<WindowData> m_WinData;

    public:
        void AddResizeCallBack(const WinSizeFunc &t) { m_WinData->m_winSizeFuncs.push_back(t); }
        void AddCloseCallBack(const WinCloseFunc &t) { m_WinData->m_winCloseFuncs.push_back(t); }
        void AddFocusCallBack(const WinFocusFunc &t) { m_WinData->m_winFocusFuncs.push_back(t); }
    
        void AddKeyPressedCallBack(const KeyPressdFunc &t) { m_WinData->m_keyPressedFuncs.push_back(t); }
        void AddKeyRepeatedCallBack(const KeyRepeatedFunc &t) { m_WinData->m_keyRepeatedFuncs.push_back(t); }
        void AddKeyReleasedCallBack(const KeyReleasedFunc &t) { m_WinData->m_keyReleasedFuncs.push_back(t); }
        void AddCharCallBack(const CharFunc &t) { m_WinData->m_charFuncs.push_back(t); }
        
        void AddMousePressedCallBack(const MousePressedFunc &t) { m_WinData->m_mousePressedFuncs.push_back(t); }
        void AddMouseReleasedCallBack(const MouseReleasedFunc &t) { m_WinData->m_mouseReleasedFuncs.push_back(t); }
        void AddScrollCallBack(const ScrollFunc &t) { m_WinData->m_scrollFuncs.push_back(t); }
        void AddCursorPosCallBack(const CursorPosFunc &t) { m_WinData->m_cursorPosFuncs.push_back(t); }

    };
}


#endif